#include"comLib\VideoEncoder.h"
#include<assert.h>
#include"global.h"


CVideoEncoder::CVideoEncoder()
{
	m_pPkt = av_packet_alloc();
	assert(m_pPkt != nullptr);
	m_pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
	assert(m_pCodec != NULL);
	m_pCodecContext = avcodec_alloc_context3(m_pCodec);
	assert(m_pCodecContext != nullptr);

	//process();


	
}

bool CVideoEncoder::init(const int width, const int height)
{
	/* put sample parameters */
	m_pCodecContext->bit_rate = 4000000;
	/* resolution must be a multiple of two */
	m_pCodecContext->width = width;
	m_pCodecContext->height = height;
	/* frames per second */
	m_pCodecContext->time_base = AVRational{ 1, 25 };
	m_pCodecContext->framerate = AVRational{ 25, 1 };

	/* emit one intra frame every ten frames
	 * check frame pict_type before passing frame
	 * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
	 * then gop_size is ignored and the output of encoder
	 * will always be I frame irrespective to gop_size
	 */
	m_pCodecContext->gop_size = 10;
	m_pCodecContext->max_b_frames = 1;
	m_pCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;

	if (m_pCodec->id == AV_CODEC_ID_H264)
	{
		av_opt_set(m_pCodecContext->priv_data, "preset", "slow", 0);
		av_opt_set(m_pCodecContext->priv_data, "tune", "zerolatency", 0);
	}

	/* open it */
	int ret = avcodec_open2(m_pCodecContext, m_pCodec, NULL);
	if (ret < 0) {
		assert(ret >-1);
		exit(1);
	}

	return 0;
}

int CVideoEncoder::sendFrame(const AVFrame *pFrame)
{
	int ret = avcodec_send_frame(m_pCodecContext, pFrame);
	if (ret < 0) {
		Global::getErrStr(ret);
		fprintf(stderr, "Error sending a frame for encoding\n");
		assert(false);
		exit(1);
	}
}

int CVideoEncoder::recvPacket(AVPacket **pPacket)
{
	int ret = 0;

	ret = avcodec_receive_packet(m_pCodecContext, m_pPkt);
	*pPacket = m_pPkt;
	return ret;
}

static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
	FILE *outfile)
{
	int ret;

	ret = avcodec_send_frame(enc_ctx, frame);
	if (ret < 0) {
		fprintf(stderr, "Error sending a frame for encoding\n");
		assert(false);
		exit(1);
	}

	while (ret >= 0) {
		ret = avcodec_receive_packet(enc_ctx, pkt);
		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
			return;
		else if (ret < 0) {
			fprintf(stderr, "Error during encoding\n");
			assert(false);
			exit(1);
		}

		printf("Write packet %lld (size=%5d)\n", pkt->pts, pkt->size);
		fwrite(pkt->data, 1, pkt->size, outfile);
		av_packet_unref(pkt);
	}
}
